package cn.emailChat.ai.filterchain.util;

import cn.emailChat.ai.config.WhitelistProperties;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @Description  白名单匹配器
 * @Author susu
 * @Date 2025/8/18
 */
@Component
public class MailWhitelist {

    private final boolean enabled;
    private final boolean allowAllIfEmpty;
    private final Set<String> exactEmails;     // 精确邮箱
    private final Set<String> domains;         // 以 "@example.com" 形式配置的域名
    private final List<Pattern> regexes;       // regex: 开头的正则
    private final List<Pattern> globs;         // 含 * 的通配符，转 regex 实现

    public MailWhitelist(WhitelistProperties props) {
        this.enabled = props.isEnabled();
        this.allowAllIfEmpty = props.isAllowAllIfEmpty();

        Set<String> exact = new HashSet<>();
        Set<String> doms = new HashSet<>();
        List<Pattern> regs = new ArrayList<>();
        List<Pattern> glb = new ArrayList<>();

        for (String raw : props.getEntries()) {
            if (raw == null || raw.trim().isEmpty()) continue;
            String s = raw.trim().toLowerCase(Locale.ROOT);

            if (s.startsWith("regex:")) {
                regs.add(Pattern.compile(s.substring("regex:".length()), Pattern.CASE_INSENSITIVE));
            } else if (s.startsWith("@")) {
                // 形如 @example.com
                doms.add(s.substring(1));
            } else if (s.contains("*")) {
                // 简易 glob -> regex
                String regex = "^" + Pattern.quote(s)
                        .replace("\\*", ".*") + "$";
                glb.add(Pattern.compile(regex, Pattern.CASE_INSENSITIVE));
            } else if (s.contains("@")) {
                exact.add(s);
            } else {
                // 兜底：无 @ 且无 * 也非 regex:，按域名处理（example.com）
                doms.add(s);
            }
        }

        this.exactEmails = Collections.unmodifiableSet(exact);
        this.domains = Collections.unmodifiableSet(doms);
        this.regexes = Collections.unmodifiableList(regs);
        this.globs = Collections.unmodifiableList(glb);
    }

    /** 主判定方法 */
    public boolean allowed(@Nullable String email) {
        if (!enabled) return true; // 未启用白名单 => 放行
        if (email == null || email.isEmpty()) return false;

        String e = email.trim().toLowerCase(Locale.ROOT);

        // entries 为空时：根据策略决定是否放行全部
        boolean noRules = exactEmails.isEmpty() && domains.isEmpty()
                && regexes.isEmpty() && globs.isEmpty();
        if (noRules) return allowAllIfEmpty;

        // 1) 精确邮箱
        if (exactEmails.contains(e)) return true;

        // 2) 域名匹配（@example.com / example.com）
        int at = e.lastIndexOf('@');
        if (at > 0 && at < e.length() - 1) {
            String dom = e.substring(at + 1);
            if (domains.contains(dom)) return true;
        }

        // 3) 通配符（glob）
        for (Pattern p : globs) {
            if (p.matcher(e).matches()) return true;
        }

        // 4) 正则
        for (Pattern p : regexes) {
            if (p.matcher(e).matches()) return true;
        }

        return false;
    }
}
